package com.treasure.mall.biz.remote.live.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tencentyun.TLSSigAPIv2;
import com.treasure.mall.biz.config.tencent.TencentConfig;
import com.treasure.mall.biz.dto.common.ChatMessageBodyDTO;
import com.treasure.mall.biz.dto.live.LiveMessageUserLevel;
import com.treasure.mall.biz.entity.live.LiveRoomPO;
import com.treasure.mall.biz.entity.live.LiveSessionPO;
import com.treasure.mall.biz.entity.user.UserPO;
import com.treasure.mall.biz.remote.live.TencentIMService;
import com.treasure.mall.biz.remote.live.TencentTools;
import com.treasure.mall.biz.remote.live.dto.*;
import com.treasure.mall.biz.remote.live.enums.MessageType;
import com.treasure.mall.biz.service.core.live.LiveRoomService;
import com.treasure.mall.biz.service.core.live.LiveSessionService;
import com.treasure.mall.zbq.common.HttpClientUtil;
import com.treasure.mall.zbq.common.HttpResult;
import com.treasure.mall.zbq.common.StringUtilsExt;
import com.treasure.mall.zbq.common.ienum.live.LiveEnums;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.nio.ByteBuffer;
import java.text.MessageFormat;
import java.util.*;

/**
 *
 * +---------------------------------------------------------
 * * @package: com.treasure.mall.biz.service.core.live.impl
 * * @author: guomw (guomwchen@foxmail.com)
 * * @date: 2020/6/11 21:42
 * * @since: V1.0.0
 * +---------------------------------------------------------
 * 注意：本内容仅限于内部传阅，禁止外泄以及用于其他的商业目的
 * Copyright 2019-2022 com.treasure.mall.biz.service.core.live.impl Inc. All rights reserved.
 */
@Slf4j
@Service
public class TencentIMServiceImpl implements TencentIMService {

    private volatile static String adminSign = "";


    @Resource
    private TencentConfig tencentConfig;
    @Autowired
    private LiveSessionService liveSessionService;
    @Autowired
    private LiveRoomService liveRoomService;

    private Random random = new Random(System.currentTimeMillis());

    private ByteBuffer byteBuffer = ByteBuffer.allocate(64);


    /**
     * 获取登录签名
     *
     * @param user
     * @param userKey
     * @return
     */
    @Override
    public Map<String, String> clientLoginInformation(UserPO user, String userKey) {
        String id = userKey;
        if (user != null) {
            id = user.toIMUserName();
        }
        return loginFor(id);
    }

    @Override
    public String clientRoom(LiveRoomPO room) {
        String id = room.toStreamName();
        newRoom(id, room.getData().getTitle());
        return id;
    }

    /**
     * 创建直播群组
     *
     * @param groupId
     * @param groupName
     * @return
     */
    @Override
    public String createGroup(String groupId, String groupName) {
        newRoom(groupId, groupName);
        return groupId;
    }


    /**
     * 状态
     *
     * @param dto
     */
    @Override
    public void sendLiveStateChangeMessage(LiveStateMessageDTO dto) {
        try {
            LiveRoomPO po = liveRoomService.findById(dto.getRoomId());
            if (po == null) {
                return;
            }
            this.sendRoomMessage(MessageBodyDTO.builder()
                    .id("id" + System.currentTimeMillis())
                    .groupId(po.toStreamName())
                    .playUrl(dto.getPlayUrl())
                    .sessionId(dto.getSessionId())
                    .type(dto.getMessageType().getDesc())
                    .build());
        } catch (Exception e) {
            log.error("sendLiveStateChangeMessage error", e);
        }
    }

    /**
     * 发送普通消息
     */
    @Override
    public void sendGeneralMessage(GeneralMessageDTO dto) {
        try {
            LiveRoomPO po = liveRoomService.findById(dto.getRoomId());
            if (po == null) {
                return;
            }
            this.sendRoomMessage(MessageBodyDTO.builder()
                    .id("id" + System.currentTimeMillis())
                    .groupId(po.toStreamName())
                    .message(dto.getMessage())
                    .name(StringUtilsExt.safeGetMobile(dto.getNick()))
                    .level(dto.getLevel())
                    .type(MessageType.general.getDesc())
                    .build());
        } catch (Exception e) {
            log.error("sendGeneralMessage error", e);
        }
    }

    /**
     * 发送禁言消息
     *
     * @param sessionId
     * @param userId
     * @param messageType
     */
    @Override
    public void sendForbidMessage(String sessionId, Long userId, MessageType messageType) {
        LiveSessionPO po = liveSessionService.findById(sessionId);
        if (po == null) {
            return;
        }
        this.sendRoomMessage(MessageBodyDTO.builder()
                .id("id" + System.currentTimeMillis())
                .groupId(po.getLiveRoomPO().toStreamName())
                .userId(userId)
                .message(messageType.equals(MessageType.enableForbid) ? "系统消息: 您已被管理员禁言" : "系统消息: 您已被管理员解除禁言")
                .type(messageType.getDesc())
                .build());
    }


    @Override
    public void sendMessage(GeneralMessageDTO dto, MessageType messageType) {
        try {
            LiveRoomPO po = liveRoomService.findById(dto.getRoomId());
            if (po == null) {
                return;
            }
            this.sendRoomMessage(MessageBodyDTO.builder()
                    .id("id" + System.currentTimeMillis())
                    .groupId(po.toStreamName())
                    .message(dto.getMessage())
                    .name(StringUtilsExt.safeGetMobile(dto.getNick()))
                    .level(dto.getLevel())
                    .type(messageType.getDesc())
                    .userId(dto.getUserId())
                    .build());
        } catch (Exception e) {
            log.error("sendGeneralMessage error", e);
        }
    }


    @Override
    public void sendChatMessage(ChatMessageBodyDTO dto) {
        try {
            this.sendRoomMessage(MessageBodyDTO.builder()
                    .id("id" + System.currentTimeMillis())
                    .groupId(dto.getGroupId())
                    .message(dto.getMessage())
                    .name(StringUtilsExt.safeGetMobile(dto.getName()))
                    .level(dto.getLevel())
                    .type(dto.getType())
                    .face(dto.getFace())
                    .userId(dto.getUserId())
                    .time(dto.getTime())
                    .build());
        } catch (Exception e) {
            log.error("sendChatMessage error", e);
        }
    }

    /**
     * 支付成功通知
     *
     * @param dto
     */
    @Override
    public void sendPayedSuccess(PayedSuccessMessageDTO dto) {
        try {
            LiveSessionPO po = liveSessionService.findById(dto.getLiveSessionId());
            if (po == null) {
                return;
            }
            this.sendRoomMessage(MessageBodyDTO.builder()
                    .id("id" + System.currentTimeMillis())
                    .groupId(po.getLiveRoomPO().toStreamName())
                    .name(StringUtilsExt.safeGetMobile(dto.getNick()))
                    .validPayOrderSum(dto.getValidPayOrderSum())
                    .level(TencentTools.getMessageUserLevel(dto.getValidPayOrderSum()))
                    .message("支付成功")
                    .type(MessageType.payed.getDesc())
                    .userId(dto.getUserId())
                    .build());
        } catch (Exception e) {
            log.error("sendPayedSuccess error", e);
        }

    }

    /**
     * 发送拍卖成功消息
     */
    @Override
    public void sendAuctionSuccess(AuctionSuccessMessageDTO dto) {
        try {
            LiveRoomPO po = liveRoomService.findById(dto.getRoomId());
            if (po == null) {
                return;
            }

            String message = MessageFormat.format("{0}出价成功", dto.getUser().getNickName());
            if (MessageType.auction.getCode().equals(dto.getMessageType().getCode())) {
                message = MessageFormat.format("恭喜 {0} 中拍！", dto.getUser().getNickName());
            }
            this.sendRoomMessage(MessageBodyDTO.builder()
                    .id("id" + System.currentTimeMillis())
                    .groupId(po.toStreamName())
                    .name(StringUtilsExt.safeGetMobile(dto.getUser().getNickName()))
                    .level(TencentTools.getMessageUserLevel(dto.getUser().getValidPayOrderSum()))
                    .message(message)
                    .type(dto.getMessageType().getDesc())
                    .userId(dto.getUser().getUserId())
                    .auctionSessionId(dto.getAuctionSessionId())
                    .money(dto.getMoney())
                    .orderId(dto.getOrderId())
                    .build());
        } catch (Exception e) {
            log.error("sendAuctionSuccess error", e);
        }
    }

    /**
     * 发送开拍通知
     *
     * @param dto
     */
    @Override
    public void sendStartAuctionMessage(AuctionStartMessageDTO dto) {
        try {
            LiveRoomPO po = liveRoomService.findById(dto.getRoomId());
            if (po == null) {
                return;
            }
            this.sendRoomMessage(MessageBodyDTO.builder()
                    .id("id" + System.currentTimeMillis())
                    .groupId(po.toStreamName())
                    .type(MessageType.auctionStart.getDesc())
                    .build());
        } catch (Exception e) {
            log.error("sendStartAuctionMessage error", e);

        }
    }

    /**
     * 发送停止通知
     *
     * @param dto
     */
    @Override
    public void sendStopAuctionMessage(AuctionStartMessageDTO dto) {
        try {
            LiveRoomPO po = liveRoomService.findById(dto.getRoomId());
            if (po == null) {
                return;
            }
            this.sendRoomMessage(MessageBodyDTO.builder()
                    .id("id" + System.currentTimeMillis())
                    .groupId(po.toStreamName())
                    .type(MessageType.auctionStop.getDesc())
                    .build());
        } catch (Exception e) {
            log.error("sendStartAuctionMessage error", e);

        }
    }

    /**
     * 发送分享成功消息
     *
     * @param dto
     */
    @Override
    public void sendShareSuccess(ShareSuccessMessageDTO dto) {
        try {
            LiveRoomPO po = liveRoomService.findById(dto.getRoomId());
            if (po == null) {
                return;
            }
            this.sendRoomMessage(MessageBodyDTO.builder()
                    .id("id" + System.currentTimeMillis())
                    .groupId(po.toStreamName())
                    .name(dto.getNick())
                    .level(TencentTools.getMessageUserLevel(dto.getValidPayOrderSum()))
                    .message("分享成功")
                    .type(MessageType.share.getDesc())
                    .userId(dto.getUserId())
                    .build());
        } catch (Exception e) {
            log.error("sendPayedSuccess error", e);
        }

    }

    /**
     * 发送商品通知
     *
     * @param dto
     */
    @Override
    public void sendGoodsTarget(GoodsTargetMessageDTO dto) {
        try {
            LiveRoomPO po = liveRoomService.findById(dto.getRoomId());
            this.sendRoomMessage(MessageBodyDTO.builder()
                    .id("id" + System.currentTimeMillis())
                    .groupId(po.toStreamName())
                    .productId(dto.getProductId())
                    .type(MessageType.assign.getDesc())
                    .userId(dto.getUserId())
                    .build());
        } catch (Exception e) {
            log.error("sendGoodsTarget error", e);
        }
    }

    /**
     * 加入直播间
     *
     * @param dto
     */
    @Override
    public void join(JoinMessageDTO dto) {
        try {
            LiveSessionPO po = liveSessionService.findById(dto.getLiveSessionId());
            if (po == null) {
                return;
            }
            this.sendRoomMessage(MessageBodyDTO.builder()
                    .id("id" + System.currentTimeMillis())
                    .groupId(po.getLiveRoomPO().toStreamName())
                    .type(MessageType.join.getDesc())
                    .level(dto.getLevel())
                    .name(dto.getName())
                    .build());
        } catch (Exception e) {
            log.error("sendGoodsTarget error", e);
        }
    }

    /**
     * 修改直播间观看人数（活跃度）
     *
     * @param roomId
     * @param memberNum
     */
    @Override
    public void modifyMemberNum(Long roomId, Integer memberNum) {
        try {
            if (memberNum == null || memberNum <= 0) {
                return;
            }
            LiveRoomPO po = liveRoomService.findById(roomId);
            if (po == null || po.currentSession() == null || po.currentSession().getPlayStatus() != LiveEnums.PlayStatus.PAYING) {
                return;
            }
            //添加活跃度
            liveSessionService.addActivityNum(po.currentSession().getId(), memberNum);
            this.sendRoomMessage(MessageBodyDTO.builder()
                    .id("id" + System.currentTimeMillis())
                    .groupId(po.toStreamName())
                    .type(MessageType.memberNum.getDesc())
                    .memberNum(memberNum)
                    .build());
        } catch (Exception e) {
            log.error("modifyMemberNum error", e);
        }

    }


    /**
     * 发布直播间红包消息
     *
     * @param dto
     */
    @Override
    public void sendRedPacketMessage(RedPacketMessageDTO dto) {
        try {
            LiveRoomPO po = liveRoomService.findById(dto.getRoomId());
            if (po == null) {
                return;
            }
            this.sendRoomMessage(MessageBodyDTO.builder()
                    .id("id" + System.currentTimeMillis())
                    .name("红包消息")
                    .message("")
                    .level(new LiveMessageUserLevel())
                    .groupId(po.toStreamName())
                    .type(dto.getMessageType().getDesc())
                    .build());
        } catch (Exception e) {
            log.error("sendRedPacketMessage error", e);
        }
    }


    /**
     * 发群消息
     * https://cloud.tencent.com/document/product/269/1629
     *
     * @param messageBodyDTO
     */
    private void sendRoomMessage(MessageBodyDTO messageBodyDTO) {
        Map<String, Object> MsgContent = new HashMap<>();
        MsgContent.put("Data", messageBodyDTO.getType());
        MsgContent.put("Desc", JSON.toJSONString(messageBodyDTO));

        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> msgBody = new HashMap<>();
        msgBody.put("MsgType", "TIMCustomElem");
        msgBody.put("MsgContent", MsgContent);
        list.add(msgBody);

        Map<String, Object> map = new HashMap<>();
        map.put("GroupId", messageBodyDTO.getGroupId());
        map.put("Random", System.currentTimeMillis() / 1000);
        map.put("MsgPriority", "High");
        map.put("MsgBody", list);

        api("group_open_http_svc", "send_group_msg", JSON.toJSONString(map));
    }


    /**
     * 发群通知
     * https://cloud.tencent.com/document/product/269/1630
     *
     * @param groupId
     * @param text
     */
    public void sendRoomNotice(String groupId, String text) {
        Map<String, Object> map = new HashMap<>();
        map.put("GroupId", groupId);
        map.put("Content", text);
        api("group_open_http_svc", "send_group_system_notification", JSON.toJSONString(map));
    }

    /**
     * 解除群组
     *
     * @param groupId
     */
    @Override
    public void destroyGroup(String groupId) {
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("GroupId", groupId);
            api("group_open_http_svc", "destroy_group", JSON.toJSONString(map));
        } catch (Exception e) {

        }
    }

    /**
     * 登录获取UserSign
     *
     * @param name
     * @return
     */
    private Map<String, String> loginFor(String name) {
        Long appId = Long.valueOf(tencentConfig.getImSdkAppId());
        String key = tencentConfig.getImSdkAppKey();
        TLSSigAPIv2 TLS = new TLSSigAPIv2(appId, key);
        long expire = 15 * 24 * 3600000;
        String sign = TLS.genSig(name, expire);
        Map<String, String> map = new HashMap<>(2);
        map.put("userID", name);
        map.put("userSig", sign);
        return map;
    }

    /**
     * // 只有音视频聊天室 没有人数上限
     * // 群名称，最长30字节，使用 UTF-8 编码，1个汉字占3个字节
     * // https://cloud.tencent.com/document/product/269/1615
     *
     * @param id
     * @param name
     */
    private void newRoom(String id, String name) {
        List<String> list = new ArrayList<>();
        list.add(id);
        Map<String, Object> map = new HashMap<>(4);
        map.put("GroupIdList", list);
        JSONObject info = Objects.requireNonNull(api("group_open_http_svc", "get_group_info", JSON.toJSONString(map))).getJSONArray("GroupInfo").getJSONObject(0);
        if (info.getInteger("ErrorCode") > 0) {
            map.clear();
            map.put("Type", "AVChatRoom");
            map.put("Name", name);
            map.put("GroupId", id);
            Object rs = api("group_open_http_svc", "create_group", JSON.toJSONString(map));
            System.out.println(rs);
        }
    }

    private JSONObject api(String service, String command, String requestData) {
        int r = random.nextInt();
        Long appId = Long.valueOf(tencentConfig.getImSdkAppId());
        String key = tencentConfig.getImSdkAppKey();
        TLSSigAPIv2 TLS = new TLSSigAPIv2(appId, key);
//        if (StringUtils.isEmpty(adminSign)) {
//        }
        adminSign = TLS.genSig(tencentConfig.getImSdkIdentifier(), 30 * 24 * 60 * 60);
//        String sign = TLS.genSig(tencentConfig.getImSdkIdentifier(), 24 * 60 * 60);
        String url = MessageFormat.format("https://console.tim.qq.com/v4/{0}/{1}?sdkappid={2}&identifier={3}&usersig={4}&random={5}&contenttype=json",
                service, command, tencentConfig.getImSdkAppId(), tencentConfig.getImSdkIdentifier(), adminSign, r);
        Map<String, String> header = new HashMap<>();
        header.put("Content-Type", "application/json");
        HttpResult httpResult = HttpClientUtil.post(url, requestData, header);
        if (httpResult.getHttpStatus() == HttpStatus.SC_OK) {
            JSONObject jsonObject = JSON.parseObject(httpResult.getHttpContent());
            Integer code = jsonObject.getInteger("ErrorCode");
            if (code == 0) {
                return jsonObject;
            }
        }
        return null;

    }
}
